// Copyright (C) 2022 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
//
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<广西木子科技有限公司>，授权编号：<NT220402151538>，代码指纹：<A.648883738.885>，技术对接人微信：<ID: Lingmuziyi>】
// 【授权寄送：<收件：李先生、地址：南宁市科园西十路11号国电智能大厦1101F、电话：17736659550、邮箱：yingshashou@vip.qq.com>】
//
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
//
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rainbowchat.im.util;

import com.eva.framework.utils.LoggerFactory;
import com.google.gson.Gson;
import com.x52im.rainbowchat.common.dto.cnst.UserProtocalsType;
import com.x52im.rainbowchat.http.logic.dto.GroupEntity;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rainbowchat.im.ChatServerEventListener;
import com.x52im.rainbowchat.im.ChatServerLauncher;
import com.x52im.rainbowchat.im.dto.CMDBody4AddFriendRequest;
import com.x52im.rainbowchat.im.dto.CMDBody4GroupNameChangedNotification;
import com.x52im.rainbowchat.im.dto.CMDBody4MyselfBeInvitedGroupResponse;
import com.x52im.rainbowchat.im.dto.CMDBody4ProcessFriendRequest;
import com.x52im.rainbowchat.im.dto.MsgBody4Group;
import com.x52im.rainbowchat.im.dto.MsgBody4Guest;
import com.x52im.rainbowchat.im.impl.OfflineMessageManager;
import com.x52im.rainbowchat.im.impl.UsersStatusManager;

import net.x52im.mobileimsdk.server.network.MBObserver;
import net.x52im.mobileimsdk.server.protocal.Protocal;
import net.x52im.mobileimsdk.server.protocal.ProtocalFactory;
import net.x52im.mobileimsdk.server.utils.GlobalSendHelper;

/**
 * 服务端主动发出的或收到的消息处理辅助类（即消息发送模式为C2S或S2C的情况）.
 *
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @version 1.0
 */
public class MessageHelper {
    /**
     * 由服务端主动发起的一条消息。
     *
     * @param to_user_id
     * @param message
     * @param QoS
     * @param typeu
     * @return
     * @throws Exception
     */
    public static void sendMessage(String to_user_id, String message, boolean QoS, int typeu
            , SendResultObserver sendResultObserver) throws Exception {
        MessageHelper.sendMessage(to_user_id, message, QoS, null, typeu, sendResultObserver);
    }

    /**
     * 由服务端主动发起的一条消息。
     *
     * @param to_user_id
     * @param message
     * @param QoS
     * @param fingerPrint        当本参数为null时，将自动生成消息指纹码，否则使用参数指定的指纹码
     * @param typeu
     * @param sendResultObserver 指令发送结果观察者（因为通信底层netty是异步通知数据发送结果的）
     * @return
     * @throws Exception
     * @see SendResultObserver
     */
    public static void sendMessage(String to_user_id, String message, boolean QoS, String fingerPrint, int typeu
            , final SendResultObserver sendResultObserver) throws Exception {
//		boolean code = false;
//		Protocal p = ProtocalFactory.createCommonData(message, "0", to_user_id, QoS, fingerPrint, typeu);
//		if(message != null && message.length()>0)
//		{
//			// @since 4.5 以前的版本：不支持与Web端im的通信
////			code = LocalSendHelper.sendData(to_user_id, message, QoS, typeu);
//			// @since 4.5 及以后版本：可支持与Web端im的通信
//			code = GlobalSendHelper.sendDataS2C(ChatServerLauncher.getInstance().getServerCoreHandler().getBridgeProcessor(), p);
//		}
//		else
//			LoggerFactory.getLog().error("[RainbowChat]message为null或length<=0，请检查参数.");
//		return new SendResult(code, p);

        final Protocal p = ProtocalFactory.createCommonData(message, "0", to_user_id, QoS, fingerPrint, typeu);
        if (message != null && message.length() > 0) {
            // netty是异步通知数据发送结果的
            MBObserver resultObserver = new MBObserver() {
                @Override
                public void update(boolean sucess, Object extraObj) {
                    if (sendResultObserver != null)
                        sendResultObserver.update(sucess, p);
                }
            };

            GlobalSendHelper.sendDataS2C(ChatServerLauncher.getInstance().getServerCoreHandler().getBridgeProcessor(), p, resultObserver);
        } else {
            LoggerFactory.getLog().error("[RainbowChat]message为null或length<=0，请检查参数.");

            if (sendResultObserver != null)
                sendResultObserver.update(false, p);
        }
    }

    // 上线消息是由服务端发出的，所以from_user_id==0（QoS==false主要用于发送上下线通知时，
    // 否则极端情况下重传的上线通知会后于下线通知，会搞乱上下线的通知罗辑）
    public static void sendOnlineMessage(String to_user_id, String user_id, SendResultObserver sendResultObserver) throws Exception {
        // 用户上线通知的格式是：上线用户uid”
        // ，形如："400005"
        sendMessage(to_user_id, user_id, false, UserProtocalsType.MT01_OF_ONLINE_NOTIVICATION, sendResultObserver);
    }

    // 下线消息是由服务端发出的，所以from_user_id==0（QoS==false主要用于发送上下线通知时，
    // 否则极端情况下重传的上线通知会后于下线通知，会搞乱上下线的通知罗辑）
    public static void sendOfflineMessage(String to_user_id, String userUid, SendResultObserver sendResultObserver) throws Exception {
        // 用户下线通知的格式是：“下线用户uid”
        // ，形如："400005"
        sendMessage(to_user_id, userUid, false, UserProtocalsType.MT02_OF_OFFLINE_NOTIVICATION, sendResultObserver);
    }

    //------------------------------------------------------------------------------- 加好友请求处理相关 S

    /**
     * 由服务端反馈给加好友发起人的错误信息头(出错的可能是：该好友
     * 已经存在于我的好友列表中、插入好友请求到db中时出错等)。
     *
     * @param to_user_id
     * @param errorMessage
     * @return
     * @throws Exception
     */
    // 此消息由服务端主动发起，所以from_user_id==0
    public static void sendAddFriendRequestResponse_for$error_server$to$aMessage(
            String to_user_id, String errorMessage, SendResultObserver sendResultObserver) throws Exception {
        sendMessage(to_user_id// 当起人的user_id=0时，服务端的QoS机制才有意义哦！
                , errorMessage, true, UserProtocalsType.MT06_OF_ADD_FRIEND_REQUEST_RESPONSE$FOR$ERROR_SERVER$TO$A, sendResultObserver);
    }

    /**
     * 解析用户发起添加好友的请求消息（添加好友请求处理：第2/3环节）.
     *
     * @param originalMsg
     * @return 客户端A发过来的加好友请求元数据封装对象
     */
    public static CMDBody4AddFriendRequest pareseAddFriendRequestMessage(String originalMsg) {
        // 加好友请求原数据（客户端A发过来的）
        CMDBody4AddFriendRequest arm = new Gson().fromJson(
                originalMsg, CMDBody4AddFriendRequest.class);
        return arm;
    }

    /**
     * 由服务端转发的加好友请求消息给在线目标用户（离线用户是不需要的哦）.
     *
     * @param to_user_id 要发送到的目标客户user_id
     * @return
     */
    public static void sendAddFriendRequestInfo_server$to$bMessage(
            String to_user_id, RosterElementEntity srcUserInfo, SendResultObserver sendResultObserver) throws Exception {
        String srcUserInfoStr = new Gson().toJson(srcUserInfo);
        sendMessage(to_user_id// 当起人的user_id=0时，服务端的QoS机制才有意义哦！
                , srcUserInfoStr, true, UserProtocalsType.MT07_OF_ADD_FRIEND_REQUEST_INFO_SERVER$TO$B, sendResultObserver);
    }

    /**
     * 解析用户B发起的处理被添加好友的请求消息：处理动作——【同意】.
     *
     * @param originalMsg
     * @return 客户端B发过来的加好友请求元数据封装对象
     */
    public static CMDBody4ProcessFriendRequest pareseProcessAdd$Friend$Req_B$To$Server_AGREEMessage(String originalMsg) {
        // 加好友请求原数据（客户端A发过来的）
        CMDBody4ProcessFriendRequest arm = new Gson().fromJson(originalMsg, CMDBody4ProcessFriendRequest.class);
        return arm;
    }

    /**
     * 解析用户B发起的处理被添加好友的请求消息：处理动作——【拒绝】.
     *
     * @param originalMsg
     * @return 客户端B发过来的加好友请求元数据封装对象
     */
    public static CMDBody4ProcessFriendRequest pareseProcessAdd$Friend$Req_B$To$Server_REJECTMessage(String originalMsg) {
        // 加好友请求原数据（客户端A发过来的）
        CMDBody4ProcessFriendRequest arm = new Gson().fromJson(originalMsg, CMDBody4ProcessFriendRequest.class);
        return arm;
    }

    /**
     * 新好友已成功被添加后，由服务端把好友信息实时反馈给客户端（
     * 此场景是被请求用户同意了加好友的请求时，由服务端把双 方的好友信息及时交给对方（如果双方有人在线的话））.
     *
     * @param to_user_id 要发送到的目标客户user_id
     * @return
     */
    // 此消息由服务端主动发起，所以from_user_id==0
    public static void sendProcessAdd$Friend$Req_friend$Info$Server$To$ClientMessage(
            String to_user_id, RosterElementEntity userInfo, SendResultObserver sendResultObserver) throws Exception {
        String userInfoStr = new Gson().toJson(userInfo);
        sendMessage(to_user_id// 当起人的user_id=0时，服务端的QoS机制才有意义哦！
                , userInfoStr, true, UserProtocalsType.MT10_OF_PROCESS_ADD$FRIEND$REQ_FRIEND$INFO$SERVER$TO$CLIENT, sendResultObserver);
    }

    /**
     * 由服务端反馈给B处理加好友请求处理时的错误信息(出错的可能是：B在提交同意A的加好友请求时出错了等)。
     *
     * @param to_user_id
     * @param errorMessage
     * @return
     * @throws Exception
     */
    // 此消息由服务端主动发起，所以from_user_id==0
    public static void sendProcessAddFriendReq_response$For$Rrror_server$to$bMessage(
            String to_user_id, String errorMessage, SendResultObserver sendResultObserver) throws Exception {
        sendMessage(to_user_id// 当起人的user_id=0时，服务端的QoS机制才有意义哦！
                , errorMessage, true, UserProtocalsType.MT11_OF_PROCESS_ADD$FRIEND$REQ_RESPONSE$FOR$ERROR_SERVER$TO$B, sendResultObserver);
    }

    /**
     * A的加好友请求被B拒绝后，由服务端把拒绝信息实时反馈给客户端A（以便A能实时知道加好友被拒的情况）.
     *
     * <p>当然，此消息被发送的前提条件是A用户此时是在线的。
     *
     * @param to_user_id 要发送到的目标客户user_id
     * @return
     */
    // 此消息由服务端主动发起，所以from_user_id==0
    public static void sendProcessAdd$Friend$Req_SERVER$TO$A_REJECT_RESULTMessage(
            String to_user_id, RosterElementEntity userInfo, SendResultObserver sendResultObserver) throws Exception {
        String userInfoStr = new Gson().toJson(userInfo);
        sendMessage(to_user_id// 当起人的user_id=0时，服务端的QoS机制才有意义哦！
                , userInfoStr, true, UserProtocalsType.MT12_OF_PROCESS_ADD$FRIEND$REQ_SERVER$TO$A_REJECT_RESULT, sendResultObserver);

    }
    //------------------------------------------------------------------------------- 加好友请求处理相关 E


    //------------------------------------------------------------------------------- 临时聊天消息处理相关S

    /**
     * 陌生人聊天消息：由服务端转发给接收人B的【步骤2/2】.
     *
     * <p>当然，此消息被发送的前提条件是B用户此时是在线的（否则临时聊天消息将被存储到DB中）。
     *
     * @param to_user_id 要发送到的目标客户user_id
     * @return
     */
    // 此消息由服务端主动发起，所以from_user_id==0
    public static void sendTempChatMsg_SERVER$TO$B_Message(
            String to_user_id, MsgBody4Guest tempChatMsgDTO, String fingerPrint, SendResultObserver sendResultObserver) throws Exception {
        String tempChatMsgDTOStr = new Gson().toJson(tempChatMsgDTO);
        sendMessage(to_user_id// 说明：因临时消息是由客户端发给服务端（代转的），客户端的QoS机制只保证到server，所以server到b也同样需要QoS=true来保证下一段的QoS哦！
                // QoS的设置原则是：由谁发起的，就由谁启用QoS机制，否则会搞乱消息的转发逻辑哦
                , tempChatMsgDTOStr, true, fingerPrint, UserProtocalsType.MT43_OF_TEMP$CHAT$MSG_SERVER$TO$B, sendResultObserver);

    }

    /**
     * 解析临时聊天消息：由发送人A发给服务端【步骤1/2】.
     *
     * @param originalMsg
     * @return 客户端A发过来的临时聊天消息：由发送人A发给服务端【步骤1/2】元数据封装对象
     */
    public static MsgBody4Guest pareseTempChatMsg_A$TO$SERVER_Message(String originalMsg) {
        // 元数据（客户端A发过来的）
        MsgBody4Guest tcmd = new Gson().fromJson(originalMsg, MsgBody4Guest.class);
        return tcmd;
    }
    //------------------------------------------------------------------------------- 临时聊天消息处理相关 E

    //------------------------------------------------------------------------------- 群聊聊天消息处理相关S

    /**
     * 群聊/世界频道聊天消息：由服务端转发给接收人B的【步骤2/2】.
     *
     * <p>当然，此消息被发送的前提条件是B用户此时是在线的（否则BBS聊天消息将不会被发送给此人哦（会自动丢弃））。
     *
     * @param to_user_id 要发送到的目标客户user_id
     * @return
     */
    // 此消息由服务端主动发起，所以from_user_id==0，但此参数目前对于接收方而言没有用处，以后可能会用上
    public static void sendGroupChatMsg_SERVER$TO$B_Message(
            String to_user_id, MsgBody4Group groupChatMsgDTO, SendResultObserver sendResultObserver) throws Exception {
        String groupChatMsgDTOStr = new Gson().toJson(groupChatMsgDTO);
        sendMessage(to_user_id
                , groupChatMsgDTOStr
                // 如需追求群发消息最大可能的性能，可设置QoS为false哦
                , true//false
                , UserProtocalsType.MT45_OF_GROUP$CHAT$MSG_SERVER$TO$B, sendResultObserver);

    }

    /**
     * 解析群聊/世界频道聊天消息：由发送人A发给服务端【步骤1/2】.
     *
     * @param originalMsg
     * @return 客户端A发过来的BBS/群组聊天消息：由发送人A发给服务端【步骤1/2】元数据封装对象
     */
    public static MsgBody4Group pareseGroupChatMsg_A$TO$SERVER_Message(String originalMsg) {
        // 元数据（客户端A发过来的）
        MsgBody4Group tcmd = new Gson().fromJson(originalMsg, MsgBody4Group.class);
        return tcmd;
    }

    /**
     * 群聊系统指令：“我”加群成功后通知“我”（即通知被加群者）（由Server发出）。
     * <p>
     * “我”可能是在创建群或群建好后邀请进入的.
     */
    public static void sendGroupSysCMD4MyselfBeInvited(String toUid
            , String newJoinUid
            , String inviteBeUid, String inviteBeNickName
            , GroupEntity groupInfo
    ) throws Exception {
        String offlineContent = "\"" + inviteBeNickName + "\"邀请你加入了群聊";

        // 准备好要发送的数据内容
        CMDBody4MyselfBeInvitedGroupResponse cmdBody = CMDBody4MyselfBeInvitedGroupResponse.copyFrom(groupInfo);
        cmdBody.setInviteBeUid(inviteBeUid);
        cmdBody.setInitveBeNickName(inviteBeNickName);
//		cmdBody.setNewJoinUid(newJoinUid);
//		cmdBody.setNewJoinNickName(newJoinNickName);

        MessageHelper.sendGroupSysCMD(UserProtocalsType.MT46_OF_GROUP$SYSCMD_MYSELF$BE$INVITE_FROM$SERVER
                , "群聊CMD-通知新加者", toUid, new Gson().toJson(cmdBody)
                , groupInfo.getG_id()
//				, groupInfo.getG_name()
                , offlineContent);
    }

    /**
     * 群聊系统指令：发出一条通用的系统信息给指定群员（由Server发出）。
     */
    public static void sendGroupSysCMD4CommonInfo(String toUid
            , String systemInfo, String gid
//			, String gname
    ) throws Exception {
//		String notificationContent = "\""+inviteBeNickName+"\"邀请\""+newJoinNickName+"\"加入了群聊";
        MsgBody4Group body = MsgBody4Group.constructGroupSystenMsgBody(gid, systemInfo);
        MessageHelper.sendGroupSysCMD(UserProtocalsType.MT47_OF_GROUP$SYSCMD_COMMON$INFO_FROM$SERVER
                , "群聊CMD-通用通知", toUid, new Gson().toJson(body)
                , gid
//				, gname
                , systemInfo);
    }

    /**
     * 群聊系统指令：发出一条群已被解散通知（由Server发出，除解散者外的所有人接收） 。
     */
    public static void sendGroupSysCMD4Dismissed(String toUid, String dismissUserName
            , String gid
//			, String gname
    ) throws Exception {
        String notificationContent = "本群已被\"" + dismissUserName + "\"解散";
        MsgBody4Group body = MsgBody4Group.constructGroupSystenMsgBody(gid, notificationContent);
        MessageHelper.sendGroupSysCMD(UserProtocalsType.MT48_OF_GROUP$SYSCMD_DISMISSED_FROM$SERVER
                , "群聊CMD-解散通知", toUid, new Gson().toJson(body)
                , gid
//				, gname
                , notificationContent);
    }

    /**
     * 群聊系统指令：发出一条"你"被踢出群聊（由Server发出，被踢者接收）。
     */
    public static void sendGroupSysCMD4YouBeRemoved(String toUid, String ownerNickname
            , String gid
//			, String gname
    ) throws Exception {
        String notificationContent = "你已被\"" + ownerNickname + "\"移出本群";
        MsgBody4Group body = MsgBody4Group.constructGroupSystenMsgBody(gid, notificationContent);
        MessageHelper.sendGroupSysCMD(UserProtocalsType.MT49_OF_GROUP$SYSCMD_YOU$BE$KICKOUT_FROM$SERVER
                , "群聊CMD-你被踢通知", toUid, new Gson().toJson(body)
                , gid
//				, gname
                , notificationContent);
    }

    /**
     * 群聊系统指令：发出一条"别人"主动退出或被群主踢出群聊（由Server发出，其它群员接收） 。
     *
     * @param himselfQuitGroup true表示本次是该人自已退群的，否则是被群主删除的
     */
    public static void sendGroupSysCMD4SomeoneRemoved(boolean himselfQuitGroup
            , String toUid, String delOprNickname, String beRemovedNickname
            , String gid
//			, String gname
    ) throws Exception {
        String notificationContent = null;

        if (himselfQuitGroup)
            notificationContent = "\"" + beRemovedNickname + "\"已退出本群";
        else
            notificationContent = "\"" + beRemovedNickname + "\"已被\"" + delOprNickname + "\"移出本群";

        MsgBody4Group body = MsgBody4Group.constructGroupSystenMsgBody(gid, notificationContent);
        MessageHelper.sendGroupSysCMD(UserProtocalsType.MT50_OF_GROUP$SYSCMD_SOMEONEB$REMOVED_FROM$SERVER
                , "群聊CMD-别人退群或被踢出通知", toUid, new Gson().toJson(body)
                , gid
//				, gname
                , notificationContent);
    }

    /**
     * 群聊系统指令：群名被修改的系统通知（由Server发出，所有除修改者外的群员接收）。
     */
    public static void sendGroupSysCMD4GroupNameChanged(String toUid
            , String changedByUid, String changedByNickName
            , String newGroupName
            , String gid) throws Exception {
        String notificationContent = "\"" + changedByNickName + "\"修改群名为\"" + newGroupName + "\"";

        // 准备好要发送的数据内容
        CMDBody4GroupNameChangedNotification cmdBody = new CMDBody4GroupNameChangedNotification();
        cmdBody.setChangedByUid(changedByUid);
        cmdBody.setNnewGroupName(newGroupName);
        cmdBody.setNotificationContent(notificationContent);
        cmdBody.setGid(gid);

        MessageHelper.sendGroupSysCMD(UserProtocalsType.MT51_OF_GROUP$SYSCMD_GROUP$NAME$CHANGED_FROM$SERVER
                , "群聊CMD-群名被改", toUid, new Gson().toJson(cmdBody), gid
//				, newGroupName
                , notificationContent);
    }

    /**
     * 发送群聊的系统级指令或通知（当接收者不在线时，本方法将自动进行离线处理）。
     *
     * @param typeu             协议类型
     * @param logTag            日志TAG
     * @param toUid             发送的对象
     * @param cmdBodyStr        要发送的协议体内容（可能是个JSON，也可能只是普通文本）
     * @param gid               发生的群id
     * @param gname             发生的群名称
     * @param contentForOffline 如果接收者不在线时，要离线保存的内容
     * @throws Exception
     */
    private static void sendGroupSysCMD(int typeu
            , final String logTag, final String toUid, String cmdBodyStr, String gid, String contentForOffline) throws Exception {
        if (cmdBodyStr != null) {
            UsersStatusManager liveMgr = ChatServerEventListener.getInstance().getLiverUsersMgr();

            // 本实例中是否在线
            final boolean isOnline = liveMgr.isOnline(toUid);

            SendResultObserver sendResultObserver = new SendResultObserver() {
                @Override
                public void update(boolean code, Protocal p) {
                    // 返回值true：对于应用层逻辑来说，无论是在线发送成功，或者是跨服桥接成功，都算是发送成功
                    if (code) {
                        LoggerFactory.getLog().info("[RBChat]【" + logTag + "】Server向" + toUid + "发送通知已成功实时发出！");

                        // 说明：满足此条件，表示本地不在线但处于与Web互通模式的情况下，消息却发送成功，也需要进行App的push通知，
                        //       因为前提是app端已不在线，进行push是合情合理的（否则桥接成功的情况下，app这边即使不在线也永远收
                        //       不到app的push通知，除非web那端也要实现不在线时的app的push通知。
                        // 备忘：此处的push逻辑是为了省去web那端不在线时的app push通知逻辑，日后支持全功能集群后，就不需
                        //       要这个逻辑了，因为包括web集群实例在内，都将是对等的且必须支持app 的push逻辑——所以没必要以下代码。
                        if (!isOnline && ChatServerLauncher.bridgeEnabled) {
                            //## 将该条指令进行离线处理
                            OfflineMessageManager.processOfflineMessage(p, true); // 注意此参数为true！
                        }
                    }
                    // 返回值false：实时或桥接发送没有成功
                    else {
                        LoggerFactory.getLog().debug("[RBChat]【" + logTag + "】Server向" + toUid
                                + "发送的通知无法实时或桥接发出(isOnline?" + isOnline + "，错误code=" + code + ")，将作离线处理【END】。");

                        //## 将该条指令进行离线处理
                        OfflineMessageManager.processOfflineMessage(p, false);
                    }
                }
            };

            // （如果用户连在本APPP实例则直发，否则开启与web互通时将桥接发）
            // 为了提升性能，QoS建议可设为false
//			MessageHelper.sendMessage(toUid, cmdBodyStr, false, typeu, sendResultObserver);
            // 20200904：为了保证群系统通知的送达率，也启用了QoS机制哦
            MessageHelper.sendMessage(toUid, cmdBodyStr, true, typeu, sendResultObserver);
        } else {
            LoggerFactory.getLog().warn("[RBChat]【" + logTag + "】cmdBodyStr is null! (toUid=" + toUid
                    + ", gid=" + gid + ", , contentForOffline=" + contentForOffline + ")");
        }
    }
    //------------------------------------------------------------------------------- 群聊聊天消息处理相关 E


//	/**
//	 * 消息发送结果封装类。
//	 */
//	public static class SendResult
//	{
//		// 发送结果：true表示成功发出，否则发出失败
//		private boolean code = false;
//		// 发送内容：返回本次发送的完整协议包内容（只是方便调用者后绪 使用，不是必须要用的）。
//		private Protocal p;
//
//		public SendResult(boolean code, Protocal p)
//		{
//			this.code = code;
//			this.p = p;
//		}
//
//		public boolean isCode()
//		{
//			return code;
//		}
//
//		public Protocal getP()
//		{
//			return p;
//		}
//	}

    /**
     * 消息发送结果封装类。
     */
    public static interface SendResultObserver {
//		// 发送结果：true表示成功发出，否则发出失败
//		private boolean code = false;
//		// 发送内容：返回本次发送的完整协议包内容（只是方便调用者后绪 使用，不是必须要用的）。
//		private Protocal p;
//
//		public SendResultObserver(boolean code, Protocal p)
//		{
//			this.code = code;
//			this.p = p;
//		}
//
//		public boolean isCode()
//		{
//			return code;
//		}
//
//		public Protocal getP()
//		{
//			return p;
//		}

        /**
         * 发送指令完成后，通过此方法来通知异步结果的观察者。
         *
         * @param code 指令发送结果：true表示成功发出，否则发出失败
         * @param p    指令发送内容：返回本次发送的完整协议包内容（只是方便调用者后绪 使用，不是必须要用的）
         */
        public void update(boolean code, Protocal p);
    }
}
